package com.gjy.mongo.sp;

import com.gjy.mongo.SlowLogListener;
import com.mongodb.MongoClientSettings;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.convert.*;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-01-30 11:01:31
 */
@Configuration
public class CustomMongoConfig {

    @Bean
    public MongoDatabaseFactory factory(MongoProperties mongo) {
        MongoClientSettings.Builder builder = MongoClientSettings.builder();
        // 用户凭证信息
//        MongoCredential credential = MongoCredential.createCredential(mongo.getUsername(), mongo.getDatabase()
//                , mongo.getPassword());
//        builder.credential(credential);
        // 服务器地址
        ServerAddress serverAddress = new ServerAddress(mongo.getHost(), mongo.getPort());
        builder.applyToClusterSettings(builder1 -> builder1.hosts(Collections.singletonList(serverAddress)));

        // 连接池
        builder.applyToConnectionPoolSettings(builder1 -> {
            builder1.minSize(2);
            builder1.maxSize(5);
        });

        // 超时参数
        builder.applyToSocketSettings(builder1 -> {
            builder1.connectTimeout(10, TimeUnit.SECONDS);
            builder1.readTimeout(30, TimeUnit.SECONDS);
        });

        // 读写配置
        builder.readPreference(ReadPreference.primaryPreferred());
        builder.retryWrites(true);

        builder.addCommandListener(new SlowLogListener(1000L));

        MongoClient client = MongoClients.create(builder.build());
        return new SimpleMongoClientDatabaseFactory(client, mongo.getDatabase());
    }

    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory,
                                                       MongoMappingContext context,
                                                       MongoCustomConversions customConversions) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
        converter.setCustomConversions(customConversions);

        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return converter;
    }

    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new CustomConvert.PersonAttrsReadConverter());
        converters.add(new CustomConvert.PersonAttrsWriteConverter());
        return new MongoCustomConversions(converters);
    }

}
